﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Printing;
using UnityScriptEngine;

namespace EnrollmentSystem
{
    public partial class frmCashDenomination : Form
    {
        UnityProcessor proc = new UnityProcessor();
        UnityScript[] dat = new UnityScript[0];
        Threader t = new Threader();

        DataTable items = new DataTable();
        string curPO = "";
        string wrnEntMsg = "";
        float gtotal = 0f;
        float totalCashDenomination = 0.0f;
        bool qtyErr = false, prcErr = false, overLessErr = false,
            cmtErr = false,Committing = false,
            isViewing = false;

        //AutoChecker
        Timer tmr = new Timer();

        public frmCashDenomination()
        {
            InitializeComponent();
            InitializeFrameSliderForm();
            
        }
        private void InitializeForm()
        {
            proc.ProcessCompleted += new ProcessHandler(proc_ProcessCompleted);
            proc.ProcessError += new ProcessHandler(proc_ProcessError);
            //Start AutoCheck timer
            LoadData();
            txtTotalCashDenomination.TextChanged += new EventHandler(CheckValue);
           // txtOverLess.TextChanged +=new EventHandler(CheckValue);
            btnCommit.Click += new EventHandler(btnCommit_Click);
            grdDenomination.CellValidated += new DataGridViewCellEventHandler(grdDenomination_CellValidated);
            t.MethodCompleted += new EventHandler(t_MethodCompleted);
            btnCommit.Visible = false;
            txtDate.LostFocus += new EventHandler(txtDate_LostFocus);
            //txtCheckNumber.Focus();
        }

        void txtDate_LostFocus(object sender, EventArgs e)
        {
            t.MethodCall(LoadData);
        }

        void grdDenomination_CellValidated(object sender, DataGridViewCellEventArgs e)
        {
            var row = grdDenomination.Rows[e.RowIndex];
            object denomination = row.Cells[0].Value;
            object pieces = row.Cells[1].Value;
            float amount = 0.0f;
            bool isNotANumber = false;

            if (denomination != null && pieces != null)
            {
                float dtype = 0.0f;
                if (denomination.ToString().Equals("Coins"))
                    dtype = 1;
                else
                    float.TryParse(denomination.ToString(), out dtype);

                amount = dtype * 1;
                float pcs = 0.0f;
                isNotANumber =  float.TryParse(pieces.ToString(), out pcs);
                if (isNotANumber)
                {
                    amount = dtype * pcs;
                }
                else
                {
                    row.Cells[1].Value = 0;
                    amount = dtype * 0;
                }

                row.Cells[2].Value = amount;
            }
            FormatDenomination();
        }
        void btnPrint_Click(object sender, EventArgs e)
        {
        }
        
        void btnCommit_Click(object sender, EventArgs e)
        {
            DialogResult dlg = MessageBox.Show("Please double check your entries before committing.\r\n" +
                "Do you wish to continue saving?", "Commit", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if (dlg == System.Windows.Forms.DialogResult.No) return;
                
            Committing = true;
            States(false);
            t.MethodCall(CommitCheck);
        }
        
        void CheckValue(object sender, EventArgs e)
        {
            t.MethodCall(CheckEntry);
        }
        //Process Ended
        void proc_ProcessError(string id, string desc)
        {
            t.SafeCall(this, delegate
            {
                
                MessageBox.Show(desc);
                States(true);
                switch (id)
                {
                    case "COMMIT":
                        Committing = false;
                        break;
                }
                tmr.Enabled = true;
            });
        }
        void proc_ProcessCompleted(string id, string desc)
        {
            t.SafeCall(this, delegate
            {
                switch (id)
                {
                    case "INITGEN":
                        t.MethodCall(LoadData);
                        break;
                    case "GENERATE":
                    case "INIT":
                        proc.DBPUX_Data_Fetch(out dat);
                        grdDenomination.DataSource = dat[0].ToDataTable();
                        t.MethodCall(LoadData);
                        break;
                    case "COMMIT":
                        btnClose_Click(null, null);
                        break;
                    case "LOAD":
                        proc.DBPUX_Data_Fetch(out dat);
                        if (dat[0].Data_Count > 0)
                        {
                            grdDenomination.DataSource = dat[0].ToDataTable();
                            UnityElement ue;
                            dat[0].Data_Get(0, out ue);
                            
                            grdDenomination.Enabled = false;
                            btnCommit.Enabled = false;
                        }
                        else
                        {
                            grdDenomination.Enabled = true;
                            grdDenomination.DataSource = dat[1].ToDataTable();
                            
                            btnCommit.Enabled = true;
                        }
                        FormatDenomination();
                        lblWarningEntry.Text = "Loaded @ " + proc.ProcEnd() + " sec.";
                        break;
                };
                if (Committing || isViewing) return;
                tmr.Enabled = true;
                States(true);
            });
        }
        void t_MethodCompleted(object sender, EventArgs e)
        {
            t.SafeCall(this, delegate
            {
                switch(sender.ToString())
                {
                    case "CheckEntry":
                        lblWarningEntry.Text = wrnEntMsg;

                        if (prcErr)
                            txtTotalCashDenomination.ForeColor = Color.Red;
                        else
                            txtTotalCashDenomination.ForeColor = Color.Black;

                        if (!prcErr)
                            btnCommit.Visible = true;
                        else
                            btnCommit.Visible = false;

                        break;
                    case "CheckContent":
                        btnCommit.Visible = !cmtErr;
                        break;
                }
                if (Committing) return;
                tmr.Enabled = true;
            });
        }

        //Operations
        void LoadData()
        {
            while (proc.IsRunning)
            {
                System.Threading.Thread.Sleep(1);
            }
            proc.ProcStart();
            UnityScript x = new UnityScript("LOAD", 4);
            x.Script_Add(Script.DBPUX_BEGIN);
            x.Script_Add(Script.DBPUX_QUERY, "SELECT fID, fDenomination AS 'Denomination', fPcs AS 'Pieces', (fDenomination * fPcs) AS 'Amount' , fStamp FROM tblcashregistry WHERE fDate = '" + txtDate.Value.ToString("yyyy-MM-dd") + "'");
            x.Script_Add(Script.DBPUX_QUERY, "SELECT fID, fDenomination AS 'Denomination', '0' AS 'Pieces', (fDenomination * 0) AS 'Amount' , fStamp FROM tbldenomination");
            x.Script_Add(Script.DBPUX_COMMIT);
            proc.Run(x);
        }
        
        void FormatDenomination()
        {
            grdDenomination.DefaultCellStyle.ForeColor = Color.Black;
            grdDenomination.Columns[0].ReadOnly = true;
            grdDenomination.Columns[2].ReadOnly = true;

            grdDenomination.Columns[1].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
            grdDenomination.Columns[2].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
            grdDenomination.Columns[2].DefaultCellStyle.Format = "#,#0.00";


            if (grdDenomination.Rows.Count > 0)
            {
                float amt = 0.0f;
                totalCashDenomination = 0.0f;
                for (int i = 0; i < grdDenomination.Rows.Count; i++)
                {
                    amt = float.Parse(grdDenomination.Rows[i].Cells[2].Value.ToString());
                    grdDenomination.Rows[i].Cells[2].Value = amt.ToString("#,#0.00");
                    grdDenomination.Rows[i].Cells[1].Value = float.Parse(grdDenomination.Rows[i].Cells[1].Value.ToString()).ToString("#,#0.00");
                    totalCashDenomination += amt;
                }
                txtTotalCashDenomination.Text = totalCashDenomination.ToString("#,#0.00");
            }
        }
        
        void CheckEntry()
        {
            float fprice = 0f, fOverLess = 0f;
            string price = txtTotalCashDenomination.Text;
            
            //Check if Commit is valid
            if (grdDenomination.Rows.Count != 0)
            {
                cmtErr = false;
            }
            else 
            {
                cmtErr = true;
            }
            //Check Price
            if (!float.TryParse(price, out fprice))
            {
                prcErr = true;
                wrnEntMsg = "";
                wrnEntMsg += "Invalid AMOUNT value detected!\r\n";
            }
            else
            {
                prcErr = false;
                if(!qtyErr) wrnEntMsg = "";
            }
           
            //Compute for the total
            gtotal = 0;
            for (int i = 0; i < items.Rows.Count; i++)
            {
                gtotal += (float)items.Rows[i]["Amount"];
            }
        }
        void CommitCheck()
        {
            UnityScript u = new UnityScript("COMMIT", 7);
            u.Script_Add(Script.DBPUX_BEGIN);
            //Construct Check Items
            u.Script_Add(Script.DBPUX_INSERT, "tblcashregistrydates (fDate)",
                    new string[] { 
                        txtDate.Value.ToString("yyyy-MM-dd")
                    });
            for (int i = 0; i < grdDenomination.Rows.Count; i++)
            {
                string deno = "";
                if (grdDenomination.Rows[i].Cells[0].Value.ToString().Equals("Coins"))
                    deno = "1";
                else
                    deno = grdDenomination.Rows[i].Cells[0].Value.ToString();

                u.Script_Add(Script.DBPUX_GENERIC, string.Format("INSERT INTO tblcashregistry (fDate, fDenomination, fPcs) "
                    +" VALUES ('{0}','{1}','{2}')", 
                    txtDate.Value.ToString("yyyy-MM-dd"),
                    float.Parse(deno).ToString(),
                    float.Parse(grdDenomination.Rows[i].Cells[1].Value.ToString()).ToString()
                    
                    ));
            }
            
            u.Script_Add(Script.DBPUX_COMMIT);
            //Wait if UnityCall is in progress.
            System.Threading.Thread.Sleep(10);
            while (proc.IsRunning)
            {

            }
            proc.Run(u);
        }
        void States(bool s)
        {
            grpDetails.Enabled = s;
        }

        //Printing Module
        
        
    }
    //Code Log:
    //- Speed up entry checking by removing the method call from the timer.
    //- Removed the CheckContent method as the CheckEntry method is sufficient for checking
    //  user inputs.
}